// $Id: zcbuffer.h 6 2011-11-19 06:33:05Z cedric.shih@gmail.com $
/*
 * Copyright 2011 Cedric Shih (cedric dot shih at gmail dot com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifndef ZCBUFFER_H_
#define ZCBUFFER_H_

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __GNUC__
#define ZCBUFFER_CHECK_FMT(a,b) __attribute__((format(printf, a, b)))
#else
#define ZCBUFFER_CHECK_FMT(a,b)
#endif

#include <sys/types.h>
#include <stdio.h>
#include <pthread.h>

const char *zcbuffer_get_version(void);

/**
 * @brief Log levels.
 */
enum zcbuffer_log_level {
	ZCBUFFER_TRACE, /**< Trivial step tracing log. */
	ZCBUFFER_DEBUG, /**< Debugging log. */
	ZCBUFFER_INFO, /**< Informative log. */
	ZCBUFFER_WARN, /**< Warning log. */
	ZCBUFFER_ERROR, /**< Error log. */
	ZCBUFFER_FATAL, /**< Fatal error log. */
};

/**
 * @brief Prototype of logger function.
 *
 * @param level - log level
 * @param func - function name
 * @param line - line number
 * @param message - log message
 */
typedef void (*zcbuffer_logger_cb)(int level,
		const char *func, unsigned int line, const char *message,
		void *arg);

/**
 * @brief Set logger function.
 *
 * @param cb - logger function
 * @see zcbuffer_logger_cb
 */
void zcbuffer_logger_set(zcbuffer_logger_cb cb, void *arg);

struct zcbuffer;

struct zcbuffer *zcbuffer_new(size_t capacity);

struct zcbuffer *zcbuffer_clone(struct zcbuffer *buffer);

void zcbuffer_free(struct zcbuffer *buffer);

struct zcbuffer *zcbuffer_slice(struct zcbuffer *buffer,
		size_t position, size_t capacity);

int zcbuffer_map(struct zcbuffer *buffer, unsigned char *data, size_t len);

int zcbuffer_resize(struct zcbuffer *buffer, size_t capacity);

int zcbuffer_get(struct zcbuffer *buffer, int *b);

int zcbuffer_peek(struct zcbuffer *buffer, size_t position, int *b);

int zcbuffer_gets(struct zcbuffer *buffer, unsigned char *data, size_t len);

int zcbuffer_get_u16(struct zcbuffer *buffer, u_int16_t *i);

int zcbuffer_get_u32(struct zcbuffer *buffer, u_int32_t *i);

int zcbuffer_peeks(struct zcbuffer *buffer, size_t position,
		unsigned char *data, size_t len);

int zcbuffer_peek_u16(struct zcbuffer *buffer, size_t position, u_int16_t *i);

int zcbuffer_peek_u32(struct zcbuffer *buffer, size_t position, u_int32_t *i);

int zcbuffer_skip(struct zcbuffer *buffer, size_t offset);

int zcbuffer_put(struct zcbuffer *buffer, int b);

int zcbuffer_puts(struct zcbuffer *buffer,
		const unsigned char *data, size_t len);

int zcbuffer_puts_b64(struct zcbuffer *buffer,
		const unsigned char *data, size_t len);

int zcbuffer_putf(struct zcbuffer *buffer,
		const char *fmt, ...) ZCBUFFER_CHECK_FMT(2,3);

struct niosocket;

ssize_t zcbuffer_read(struct zcbuffer *buffer, int fd);

ssize_t zcbuffer_write(struct zcbuffer *buffer, int fd);

int zcbuffer_load(struct zcbuffer *buffer, struct zcbuffer *source);

unsigned char *zcbuffer_array(struct zcbuffer *buffer);

size_t zcbuffer_capacity(struct zcbuffer *buffer);

size_t zcbuffer_position(struct zcbuffer *buffer);

int zcbuffer_set_position(struct zcbuffer *buffer, size_t position);

size_t zcbuffer_limit(struct zcbuffer *buffer);

int zcbuffer_set_limit(struct zcbuffer *buffer, size_t limit);

size_t zcbuffer_remaining(struct zcbuffer *buffer);

void zcbuffer_clear(struct zcbuffer *buffer);

void zcbuffer_flip(struct zcbuffer *buffer);

void zcbuffer_rewind(struct zcbuffer *buffer);

void zcbuffer_mark(struct zcbuffer *buffer);

int zcbuffer_reset(struct zcbuffer *buffer);

int zcbuffer_compact(struct zcbuffer *buffer);

enum zcbuffer_hexdump_format {
	ZCBUFFER_HEXDUMP_SIMPLE,
};

void zcbuffer_hexdump(struct zcbuffer *buffer,
		enum zcbuffer_hexdump_format format,
		char *dest, size_t len);

void zcbuffer_hexdump_file(struct zcbuffer *buffer,
		enum zcbuffer_hexdump_format format,
		FILE *file, size_t len);

enum zcbuffer_event_type {
	ZCBUFFER_EVENT_RELEASING,
};

typedef void (*zcbuffer_cb)(struct zcbuffer *buffer,
		enum zcbuffer_event_type type, void *arg);

void zcbuffer_set_cb(struct zcbuffer *buffer,
		zcbuffer_cb cb, void *cbarg);

enum zcheap_type {
	ZCHEAP_UNKNOWN,
	ZCHEAP_CIRCULAR,
};

struct zcheap *zcheap_new(enum zcheap_type type,
		unsigned int capacity);

void zcheap_free(struct zcheap *heap);

size_t zcheap_capacity(struct zcheap *heap);

void zcheap_set_lock(struct zcheap *heap, pthread_mutex_t *lock);

struct zcbuffer *zcheap_alloc(struct zcheap *heap, size_t len);

int zcheap_realloc(struct zcheap *heap, struct zcbuffer *buffer, size_t len);

int zcheap_reset(struct zcheap *heap);

struct zcbuffer *zcheap_read(struct zcheap *heap);

struct zcheap_stat {
	unsigned int count;
	unsigned int put;
	unsigned int dropped;
};

int zcheap_stat(struct zcheap *heap,
		struct zcheap_stat *stat);

struct zcqueue;

struct zcqueue *zcqueue_new(void);

void zcqueue_free(struct zcqueue *queue);

size_t zcqueue_size(struct zcqueue *queue);

int zcqueue_clear(struct zcqueue *queue);

struct timeval;

int zcqueue_put(struct zcqueue *queue,
		const struct timeval *timestamp, struct zcbuffer *buffer);

struct zcbuffer *zcqueue_take(struct zcqueue *queue,
		struct timeval *timestamp);

int zcqueue_take_newer(struct zcqueue *queue,
		struct zcqueue *dest, const struct timeval *timestamp);

int zcqueue_take_older(struct zcqueue *queue,
		struct zcqueue *dest, const struct timeval *timestamp);

struct zcbuffer *zcqueue_peek(struct zcqueue *queue,
		struct timeval *timestamp);

#ifdef __cplusplus
}
#endif

#endif /* ZCBUFFER_H_ */
